package top.igotcha.chapter.chapter8.stampedLock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.StampedLock;

import static java.lang.Thread.sleep;

/**
 * @author Gotcha
 * @date 2021/3/19
 * @describe
 */
public class StampedLockTest01 {
    public static void main(String[] args) throws InterruptedException {
        DataContainerStamped container = new DataContainerStamped(1);
        new Thread(()->container.read(2000)).start();
        //new Thread(()->container.read(2000)).start();
        sleep(1000);
        new Thread(()->container.write(2)).start();
    }
}
@Slf4j(topic = "DataContainerStamped")
class DataContainerStamped{
    private int data;
    private final StampedLock lock = new StampedLock();

    public DataContainerStamped(int data) {
        this.data = data;
    }

    public int read(int readTime){
        long stamp = lock.tryOptimisticRead();
        log.debug("加锁,乐观读锁，{}",stamp);
        try {
            sleep(readTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (lock.validate(stamp)){
            log.debug("解锁,乐观读锁，{}",stamp);
            return data;
        }

        //锁升级-乐观锁升级为读锁
        log.debug("更新,读锁，{}",stamp);
        try {
            stamp = lock.tryReadLock();
            log.debug("加锁,正常读锁，{}",stamp);
            sleep(readTime);
            log.debug("读取结束，{}",stamp);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            log.debug("解锁,正常读锁，{}",stamp);
            lock.unlockRead(stamp);
        }
        return data;
    }

    public void write(int newData){
        long stamp = lock.writeLock();
        log.debug("加锁,写锁，{}",stamp);
        try {
            sleep(1000);
            this.data = newData;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.debug("解锁,写锁，{}",stamp);
            lock.unlockWrite(stamp);
        }
    }
}
